﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Xml.Linq;

namespace Bing
{
    /// <summary>
    /// Contains classes for responses and errors returned by all <see cref="ApiHelper.SourceType"/>s, as well as properties indicating version.
    /// </summary>
    [DebuggerDisplay("Version:{Version}")]
    public class SearchResponseBase
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="SearchResponseBase"/> class.
        /// </summary>
        public SearchResponseBase(XContainer element)
        {
            fillProperties(element);
        }

        /// <summary>
        /// The version of the Bing API response object that sent this response.
        /// </summary>
        /// <value>The version.</value>
        public string Version { get; set; }

        /// <summary>
        /// Gets or sets the properties related to Bing's query-alteration functionality.
        /// </summary>
        /// <value>Contains properties related to Bing's query-alteration functionality.</value>
        public Query AlteredQuery { get; set; }

        /// <summary>
        /// Gets or sets the List of API errors.
        /// </summary>
        /// <value>The List of API errors.</value>
        public List<Error> Errors {get; set;}

        /// <summary>
        /// Fills the properties.
        /// </summary>
        /// <param name="element">The element.</param>
        private void fillProperties(XContainer element)
        {
            // Version
            XAttribute version = ((XElement)element).Attribute(XName.Get("Version", ApiHelper.BingNs));
            if (version != null)
                Version = version.Value;

            // Altered Query
            AlteredQuery = getAlteredQuery(element);

            // Errors
            Errors = getApiErrors(element);
        }

        /// <summary>
        /// Gets the altered query.
        /// </summary>
        /// <param name="document">The document.</param>
        /// <returns></returns>
        private static Query getAlteredQuery(XContainer document)
        {
            XElement element = document.Element(XName.Get("Query", ApiHelper.BingNs));
            if (element == null) return new Query();

            Query query = new Query();
            query.AlterationQueryOverride = ApiHelper.GetElementValueOrDefault<string>(element, "AlterationOverrideQuery", ApiHelper.BingNs);
            query.SearchTerms = ApiHelper.GetElementValueOrDefault<string>(element, "SearchTerms", ApiHelper.BingNs);
            query.AlteredQuery = ApiHelper.GetElementValueOrDefault<string>(element, "AlteredQuery", ApiHelper.BingNs);
            return query;
            
        }

        /// <summary>
        /// Gets the API errors.
        /// </summary>
        /// <param name="document">A <see cref="XElement"/> with the API results..</param>
        /// <returns>A List of <see cref="Error"/>s.</returns>
        private static List<Error> getApiErrors(XContainer document)
        {

            if (document == null) return new List<Error>();

            IEnumerable<XNode> nodes = document.Descendants(XName.Get("Errors", ApiHelper.BingNs)).Nodes();
            if (nodes.Count() > 0)
            {
                var errors = from error in nodes
                             select new Error
                                        {
                                            Code = ApiHelper.GetElementValueOrDefault<UInt32>(error, "Code", ApiHelper.BingNs),
                                            Message = ApiHelper.GetElementValueOrDefault<string>(error, "Message", ApiHelper.BingNs),
                                            HelpUrl = ApiHelper.GetElementValueOrDefault<string>(error, "HelpUrl", ApiHelper.BingNs),
                                            Parameter = ApiHelper.GetElementValueOrDefault<string>(error, "Parameter", ApiHelper.BingNs),
                                            Value = ApiHelper.GetElementValueOrDefault<string>(error, "Value", ApiHelper.BingNs),
                                            SourceType = ApiHelper.GetElementValueOrDefault<string>(error, "SourceType", ApiHelper.BingNs),
                                            SourceTypeErrorCode = ApiHelper.GetElementValueOrDefault<UInt32>(error, "SourceTypeErrorCode", ApiHelper.BingNs)
                                        };
                return errors.ToList();
            }

            return new List<Error>();
        }
    }
}


